package com.xnf.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xnf.article.feigh.AdminFeign;
import com.xnf.article.mapper.ApArticleMapper;
import com.xnf.article.service.HotArticlesService;
import com.xnf.common.constants.article.ArticleConstants;
import com.xnf.model.admin.pojos.AdChannel;
import com.xnf.model.article.pojos.ApArticle;
import com.xnf.model.article.vo.HotArticleVo;
import com.xnf.model.common.dtos.ResponseResult;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by xnf on 2022/3/18.
 */
@Service
@Transactional
public class HotArticleServiceImpl implements HotArticlesService {

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private ApArticleMapper apArticleMapper;
    @Autowired
    private AdminFeign adminFeign;

    /**
     * 定时 计算热点文章数据
     */
    @Override
    public void computeHotArticle() {
        //1.查询前5天的文章数据
        String dayParam = DateTime.now().minusDays(5).toString("yyyy-MM-dd HH:mm:ss");
        List<ApArticle> apArticles = apArticleMapper.selectList(Wrappers.<ApArticle>lambdaQuery().gt(ApArticle::getPublishTime, dayParam));

        //2.计算文章分值
        List<HotArticleVo> hotArticleVoList = getArticleScore(apArticles);
        //3.为每一个频道缓存热点较高的30条文章
        cacheTagToRedis(hotArticleVoList);
    }

    /**
     * 给每一个频道缓存分值较高的30条数据
     *
     * @param hotArticleVoList
     */
    private void cacheTagToRedis(List<HotArticleVo> hotArticleVoList) {
        if (hotArticleVoList != null && hotArticleVoList.size() > 0){
            //1.查询所有的频道
            ResponseResult responseResult = adminFeign.selectAllChannel();
            List<AdChannel> channels = JSON.parseArray(JSON.toJSONString(responseResult.getData()), AdChannel.class);
            for (AdChannel adChannel : channels){
                List<HotArticleVo> hotArticleVos = hotArticleVoList.stream().filter(x -> x.getChannelId().equals(adChannel.getId())).collect(Collectors.toList());
                //3.给每个频道进行缓存
                sortAndCache(hotArticleVos, ArticleConstants.HOT_ARTICLE_FIRST_PAGE + adChannel.getId());
            }
            //4.给推荐频道缓存30条数据  所有文章排序之后的前30条
            sortAndCache(hotArticleVoList,ArticleConstants.HOT_ARTICLE_FIRST_PAGE+ArticleConstants.DEFAULT_TAG);
        }
    }

    /**
     * 排序并缓存
     *
     * @param hotArticleVoList
     * @param redisKey
     */
    private void sortAndCache(List<HotArticleVo> hotArticleVoList, String redisKey) {
        hotArticleVoList.sort(new Comparator<HotArticleVo>() {
            @Override
            public int compare(HotArticleVo o1, HotArticleVo o2) {
                return o2.getScore().compareTo(o1.getScore());
            }
        });
        if (hotArticleVoList.size() > 30) {
            hotArticleVoList = hotArticleVoList.subList(0, 30);
        }
        String value = JSON.toJSONString(hotArticleVoList);
        System.out.println(redisKey +"::"+value);
        redisTemplate.opsForValue().set(redisKey, JSON.toJSONString(hotArticleVoList));
    }

    /**
     * 计算文章的分值
     *
     * @param apArticles
     * @return
     */
    private List<HotArticleVo> getArticleScore(List<ApArticle> apArticles) {
        if (apArticles != null && apArticles.size() > 0) {
            List<HotArticleVo> hotArticleVos = new ArrayList<>();
            HotArticleVo hotArticleVo = null;
            for (ApArticle apArticle : apArticles) {
                hotArticleVo = new HotArticleVo();
                BeanUtils.copyProperties(apArticle, hotArticleVo);
                Integer score = computeScore(apArticle);
                hotArticleVo.setScore(score);
                hotArticleVos.add(hotArticleVo);
            }
            return hotArticleVos;
        }
        return null;
    }

    /**
     * 计算某一个文章的分值
     *
     * @param apArticle
     * @return
     */
    public Integer computeScore(ApArticle apArticle) {
        Integer score = 0;
        if (apArticle.getLikes() != null) {
            score += apArticle.getLikes() * ArticleConstants.HOT_ARTICLE_LIKE_WEIGHT;
        }
        if (apArticle.getViews() != null) {
            score += apArticle.getViews();
        }
        if (apArticle.getComment() != null) {
            score += apArticle.getComment() * ArticleConstants.HOT_ARTICLE_COMMENT_WEIGHT;
        }
        if (apArticle.getCollection() != null) {
            score += apArticle.getCollection() * ArticleConstants.HOT_ARTICLE_COLLECTION_WEIGHT;
        }
        return score;
    }
}
